#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <mysql_connection.h>

#include <cstdlib>
#include <iostream>
#include <memory>

using namespace std;

int main(void) {
    try {
        sql::Driver* driver = get_driver_instance();
        std::unique_ptr<sql::Connection> conn(
            driver->connect("tcp://127.0.0.1:3306", "root", "123456"));
        conn->setSchema("chat");  // 设置数据库

        // 数据查询操作
        std::unique_ptr<sql::Statement> stmt(conn->createStatement());
        std::unique_ptr<sql::ResultSet> res(
            stmt->executeQuery("SELECT 'Hello World!' AS _message"));

        while (res->next()) {
            cout << "别名或列名访问：";
            // 使用别名或列名访问
            cout << res->getString("_message") << endl;
            cout << "索引访问，从1开始:";
            // 使用列索引访问，从1开始
            cout << res->getString(1) << endl;
        }

        stmt->execute("DROP TABLE IF EXISTS test");
        stmt->execute("CREATE TABLE test(id INT)");

        // 数据更新操作
        std::unique_ptr<sql::PreparedStatement> pstmt(
            conn->prepareStatement("INSERT INTO test(id) VALUES(?)"));
        for (int i = 1; i <= 10; ++i) {
            pstmt->setInt(1, i);
            pstmt->executeUpdate();
        }

        pstmt = std::unique_ptr<sql::PreparedStatement>(
            conn->prepareStatement("SELECT id FROM test ORDER BY id ASC"));
        res = std::unique_ptr<sql::ResultSet>(pstmt->executeQuery());

        res->afterLast();  // 逆序获取数据
        while (res->previous()) {
            std::cout << "逆序获取：" << res->getInt("id") << std::endl;
        }

    } catch (sql::SQLException& e) {
        cout << "# ERR: SQLException in " << __FILE__;
        cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
        cout << "# ERR: " << e.what();
        cout << " (MySQL error code: " << e.getErrorCode();
        cout << ", SQLState: " << e.getSQLState() << " )" << endl;
    }

    cout << endl;

    return EXIT_SUCCESS;
}
